﻿using System;
using SimpleServiceBus.Bus.Transport;
using SimpleServiceBus.Endpoint;
using SimpleServiceBus.Utilities.ObjectBuilder;
using SimpleServiceBus.Utilities.ServiceManager;

namespace SimpleServiceBus.Endpoint
{
    public class EndpointServiceManager : LocalServiceManager
    {

        public EndpointServiceManager(IMessagingEndpoint endpoint)
        {
            if (endpoint == null)
                throw new ArgumentNullException("endpoint");
            Endpoint = endpoint;
        }

        public IMessagingEndpoint Endpoint { get; private set; }

        public override void RegisterService<T>(T serviceImplementation)
        {
            if (serviceImplementation != null)
            {
                if (typeof(IEndpointService).IsAssignableFrom(serviceImplementation.GetType()))
                {
                    ((IEndpointService) serviceImplementation).Endpoint = Endpoint;
                }
            }

            if (HasService<IObjectBuilderService>())
                GetService<IObjectBuilderService>().RegisterSingleton<T>(serviceImplementation);

            base.RegisterService<T>(serviceImplementation);
        }

        protected override void StartService()
        {
            base.StartService();

            //ITransport should always be the last service to start
            //because starting the transport will cause it to 
            //crank up its worker threads and start pulling
            //messages off the queue. We want the whole train
            //out of the station before this happens.
            StartTransportService();
        }

        protected override void StartLocalService(object service)
        {
            //We'll save the Transport for last
            if (typeof(ITransport).IsAssignableFrom(service.GetType()) == false)
            {
                base.StartLocalService(service);
            }
        }

        //Finally, we shall start thee, dear Transport
        protected virtual void StartTransportService()
        {
            var transport = GetService<ITransport>();
            if (transport != null)
                transport.Start();
        }
    }
}